package com.tnsw.facebookautoliker;

import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.TimeZone;

import org.json.JSONArray;
import org.json.JSONObject;

import com.tnsw.coreutils.MyLog;
import com.tnsw.coreutils.database.RecordBase;
import com.tnsw.coreutils.text.TextUtils;
import com.tnsw.coreutils.ui.BitmapCache;
import com.tnsw.facebookautoliker.database.DBManager;
import com.tnsw.facebookautoliker.database.FriendsList;
import com.tnsw.facebookautoliker.database.FriendsPost;
import com.tnsw.facebookautoliker.database.ObjectCache;
import com.tnsw.facebookautoliker.database.VFriendsPost;
import com.tnsw.facebookautoliker.helper.FacebookBGManager;
import com.tnsw.facebookautoliker.helper.GeneralManager;
import com.tnsw.facebookautoliker.helper.command.DoUnlikePost;
import com.tnsw.facebookautoliker.helper.command.GetOtherInfo;
import com.tnsw.facebookautoliker.helper.command.GetPhoto;
import com.tnsw.facebookautoliker.helper.command.GetPhotoFQL;
import com.tnsw.facebookautoliker.helper.command.LikeManager;
import com.tnsw.facebookautoliker.services.AutoLikerService;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class LikeHistoryAdapter extends BaseAdapter implements OnClickListener, OnLongClickListener, OnLayoutChangeListener {

	private LayoutInflater inflater = null;
	private String tag = "LikeHistoryAdapter";
	private Context context;
	private ArrayList<RecordBase> arrHistory = new ArrayList<RecordBase>();
	private ArrayList<RecordBase> arrFiltered = new ArrayList<RecordBase>();
	
	private GeneralManager gm;
	private FacebookBGManager fbm;
	private DBManager dbm;
	private AutoLikerService service;
	
	private View emptyView;
	private BitmapCache bCache;
	private String filterName = "";
	
	private StandardUpdateView stdUpdateView;
	private boolean isOnlyFriend = false;
	private Bitmap bmpLike;
	
	private Hashtable<String, ArrayList<String>> hashObjectCache;
	
	public LikeHistoryAdapter(Context context, View emptyView, StandardUpdateView stdUpdateView) {
		super();
		this.context = context;
		this.emptyView = emptyView;
		this.stdUpdateView = stdUpdateView;
		
		this.gm = GeneralManager.getInstance();
		this.fbm = FacebookBGManager.getInstance(context);
		this.dbm = DBManager.getInstance(context);
		this.service = AutoLikerService.getInstance();
		
		this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		this.bmpLike = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.like_icon);
		this.refreshFromDB();
		
		this.hashObjectCache = new Hashtable<String, ArrayList<String>>();
	}
	
	public void setDisplayOnlyFriend(boolean b) {
		this.isOnlyFriend = b;
		this.updateFileredArrayList();
	}
		
	public void setBitmapCache(BitmapCache bCache) {
		this.bCache = bCache;
	}
	
	public ArrayList<RecordBase> getArrHistory() {
		return(this.arrHistory);
	}
	
	public void refreshFromDB() {
		if (this.arrHistory != null) {
			this.arrHistory.clear();
		}
		
		String sql = "select * from friends_post where status_text='" + LikeManager.S_LINK_POSTED + "' order by created_time desc";
		sql = "select * from friends_post where liked='Y' order by created_time desc";
		sql = "select * from friends_post order by created_time desc";
		
		ArrayList<RecordBase> a = null;
		
		a = this.dbm.getRecords(FriendsPost.class.getName(), sql, null, 0);
		if (a != null) {
			this.arrHistory = a;
			MyLog.d(tag, "record_size=" + this.arrHistory.size());
			int len = this.arrHistory.size();
			int i;
			for (i = 0; i < len; i++) {
				FriendsPost fp = (FriendsPost) this.arrHistory.get(i);
				if (fp.status_text.equals(LikeManager.S_ELSE)) {
					try {
						//JSONObject jo = new JSONObject(fp.raw_json);
						int type = -1;
						type = fp.type;
						
						/*
						FriendsList fl = null;
						if (this.service.getHashFriendsList().containsKey(fp.actor_id) == true) {
							fl = this.service.getHashFriendsList().get(fp.actor_id);
							String newStatusText = LikeManager.getType(jo, fl.name);
							if (newStatusText.equals(fp.status_text) == false) {
								fp.status_text = newStatusText;
							}
						}
						*/
						
					} catch (Exception e) {
						MyLog.e(tag, "refreshFromDB() - " + e.toString(), e);
					}
				}
			}
			
		} else {
			MyLog.d(tag, "arrHistory is null");
		}
		
		if (this.filterName.equals("") == false) {
			this.updateFileredArrayList();
		}
		
	}
	
	@Override
	public int getCount() {
		//MyLog.d(tag, "GetCount()");
		ArrayList<RecordBase> currentArr = this.getCurrentArrayList();
		if (currentArr == null) {
			if (this.stdUpdateView.getCurrentStage() == 2) {
				MyLog.d(tag, "return(0)");
				return(0);
			}
			return(1);
			
		}
		
		if (currentArr.size() == 0) {
			if (this.stdUpdateView.getCurrentStage() == 2) {
				MyLog.d(tag, "return(0)");
				return(0);
			} 
			return(1);
		}
		
		return(currentArr.size());
	}

	@Override
	public Object getItem(int position) {
		ArrayList<RecordBase> currentArr = this.getCurrentArrayList();
		if (currentArr == null) return(null);
		
		return(currentArr.get(position));
	}

	@Override
	public long getItemId(int position) {
		return (position);
	}
	
	public ArrayList<RecordBase> getCurrentArrayList() {
		ArrayList<RecordBase> currentArr;
		
		if (this.filterName.equals("") == false) {
			currentArr = this.arrFiltered;
			//MyLog.d(tag, "use Filter");
		} else if (this.isOnlyFriend == true) {
			currentArr = this.arrFiltered;
			//MyLog.d(tag, "use Filter");
		} else {
			currentArr = this.arrHistory;
			//MyLog.d(tag, "use Full");
		}
		
		return(currentArr);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ArrayList<RecordBase> currentArr = this.getCurrentArrayList();
		
		boolean isEmpty = false;
		
		if (currentArr == null) {
			isEmpty = true;
		} else if (currentArr.size() == 0) {
			isEmpty = true;
		}
		
		if (isEmpty) {
			
			if (this.stdUpdateView.getCurrentStage() == 2) {
				
			}
			
			TextView tvEmpty = (TextView) this.emptyView.findViewById(R.id.tvEmpty);
			if (this.filterName.equals("")) {
				tvEmpty.setText("Pull down to refresh");
			} else {
				tvEmpty.setText("Cannot find '" + this.filterName + "', pull down to refresh");
			}
			
			return(this.emptyView);
		}
		
		FriendsPost fp = (FriendsPost) currentArr.get(position);
		TextView tv = new TextView(this.context);
		String stt = fp.status_text;
		FriendsList fl = null;
		
		String name = null;
		String photo_path = null;
		
		fl = this.service.getHashFriendsList().get(fp.actor_id);
		if (fl != null) {
			name = fl.name;
			photo_path = fl.photo_path;
		}
				
		if (name != null) {
			stt = stt + " from " + name;
		} else {

			stt = stt + " from <unknown-" + fp.actor_id + ">";
			MyLog.d(tag, "Getting other now..actor_id=" + fp.actor_id);
			GetOtherInfo oInfo = new GetOtherInfo(this.context, fp.actor_id);
			oInfo.setRequiredSignature(true);
			this.gm.addNewQueue(oInfo, 2);
			
		}
				
		tv.setText(stt);
		
		RelativeLayout item = (RelativeLayout) this.inflater.inflate(R.layout.likehistory_item, null);
		RelativeLayout layoutItemWait = (RelativeLayout) item.findViewById(R.id.layoutItemWait);
		
		layoutItemWait.setAlpha(10l);
		item.setTag(R.id.tag_record, fp);
		item.setTag(R.id.tag_position, position);
		
		if (fp.getHeight() != 0) {
			layoutItemWait.getLayoutParams().height = fp.getHeight();
			layoutItemWait.requestLayout();
		} else {
			item.addOnLayoutChangeListener(this);	
		}
		
		//MyLog.d(tag, "position=" + position + ", getStatus=" + fp.getStatus());
		
		if (fp.getStatus() == 0) {
			layoutItemWait.setVisibility(View.GONE);	
		} else {
			layoutItemWait.setVisibility(View.VISIBLE);
		}
		
				
		if (this.filterName.equals("") == false) {
			
			if ( (fp != null) && (name != null) && (name.toLowerCase().contains(this.filterName.toLowerCase()) == false) ) {
				item.setVisibility(View.GONE);
				int i;
				for (i = 0; i < item.getChildCount(); i++) {
					View vg = (View) item.getChildAt(i);
					vg.setVisibility(View.GONE);
				}
				
				MyLog.d(tag, "why return here?");
				return(item);
			}
		}
		
		
		TextView tvFriendName = (TextView) item.findViewById(R.id.tvFriendName);
		
		
		TextView tvLikeUnlike = (TextView) item.findViewById(R.id.tvLikeUnlike);
		tvLikeUnlike.setOnClickListener(this);
		tvLikeUnlike.setFocusable(false);
		tvLikeUnlike.setFocusableInTouchMode(false);
		tvLikeUnlike.setTag(R.id.tag_position, position);
		
		TextView tvWhen = (TextView) item.findViewById(R.id.tvWhen);
		ImageView imgLike = (ImageView) item.findViewById(R.id.imgLike);
		imgLike.setImageBitmap(this.bmpLike);
		TextView tvLikeCount = (TextView) item.findViewById(R.id.tvLikeCount);
		
		if (fp.liked.equals("Y")) {
			tvLikeUnlike.setText("Unlike");
		} else {
			tvLikeUnlike.setText("Like");
		}
		
		if (fp.can_like.equals("N")) {
			tvLikeUnlike.setVisibility(View.GONE);
		}
		
		tvFriendName.setText(stt);
		String stdDate = TextUtils.getMyStandardDateStr(fp.created_time*1000, TimeZone.getDefault().getID());
		tvWhen.setText(stdDate);
		tvWhen.setTag(R.id.tag_tvWhen_mode, 0);  // tag=mode=0
		tvWhen.setTag(R.id.tag_position, position);
		tvWhen.setFocusable(false);
		tvWhen.setFocusableInTouchMode(false);
		tvWhen.setOnClickListener(this);
		tvWhen.setOnLongClickListener(this);
		
		if (fp.getWhenMode() == 1) {
			String fbDateTime = TextUtils.getFBDateDiff(fp.created_time*1000, System.currentTimeMillis());
			tvWhen.setText(fbDateTime);
		}
		
		
		//tvWhen.setText(String.valueOf(fp.created_time) + " " + System.currentTimeMillis());
		
		tv.setText(stt);
				
		ImageView imgFriendPhoto = (ImageView) item.findViewById(R.id.imgFriendPhoto);
		
		if ( (photo_path != null) && (photo_path.equals("") == false) ) {

			Bitmap bmp = this.bCache.getBitmap(photo_path);
			if (bmp != null) {
				imgFriendPhoto.setImageBitmap(bmp);
			
			}
			
		} 
		
		if (photo_path != null) {
			try {
				File ff = new File(photo_path);
				if (ff.exists() == false) {
					MyLog.e(tag, "file not exists, '" + photo_path + "'");
					GetPhoto gp = new GetPhoto(this.context, fp.actor_id, name);
					this.gm.addNewQueue(gp, 2);
				}	
			} catch (Exception e) {
				MyLog.e(tag, "getView() - fp.photo_path='" + photo_path + "' throw Exception - " + e.toString(), e);
			}
			
		} else {
			MyLog.w(tag, "getView() - photo_path = null");
		}
		
		LinearLayout llDetail = (LinearLayout) item.findViewById(R.id.llDetail);
		TextView tvMessage = new TextView(this.context);
		
		if (fp != null) {
			try {

				String description = "";
				
				int likeCount = fp.like_count;
				if (likeCount == 0) {
					imgLike.setVisibility(View.GONE);
					tvLikeCount.setVisibility(View.GONE);
				} else {
					imgLike.setVisibility(View.VISIBLE);
					tvLikeCount.setVisibility(View.VISIBLE);
					tvLikeCount.setText(String.valueOf(likeCount));
				}
					
				description = fp.description;
				String message = fp.message;
				if (message == null || message.equals("")) {
					if (description != null) {
						message = description;
					}
				}
				
				ArrayList<String> a = null;
				if (this.hashObjectCache.containsKey(fp.post_id) == false) {
					ArrayList<RecordBase> objCacheRecords = this.dbm.getRecords(ObjectCache.class.getName(), "select fbid from object_cache where post_id=?", new String[] {fp.post_id}, 0);
					if (objCacheRecords != null) {
						ArrayList<String> arrFbid = new ArrayList<String>();
						int i;
						for (i = 0; i < objCacheRecords.size(); i++) {
							ObjectCache oc = (ObjectCache) objCacheRecords.get(i);
							arrFbid.add(oc.fbid);
						}
						
						a = arrFbid;
						this.hashObjectCache.put(fp.post_id, a);
						MyLog.d(tag, "created new hashObjectCache Item");
					}
										
				} else {
					a = this.hashObjectCache.get(fp.post_id);
					MyLog.d(tag, "reuse hashObjectCache");
				}
								
				if (a != null) {
					HorizontalScrollView attachmentV = (HorizontalScrollView) this.inflater.inflate(R.layout.attachments, null);
					attachmentV.setFocusable(false);
					attachmentV.setFocusableInTouchMode(false);
					LinearLayout llAttachment = (LinearLayout) attachmentV.findViewById(R.id.llAttachments);
												
					for (String fbid : a) {

						ArrayList<RecordBase> aa = this.dbm.getRecords(ObjectCache.class.getName(), "select fbid, local_path, attempt from object_cache where fbid=?", new String[] {fbid}, 0);
						if (aa != null) {
							ObjectCache oc = (ObjectCache) aa.get(0);

							if ( (oc.local_path != null) && (oc.local_path.equals("") == false) ) {
								ImageView img1 = new ImageView(this.context);
								
								Bitmap bmp = this.bCache.getBitmap(oc.local_path);
									
								if (bmp == null) {
									File f = new File(oc.local_path);
									if (f.exists() == true) {
										MyLog.w(tag, "(unsupported format) cannot load bitmap=" + oc.local_path);	
									} else {
										MyLog.e(tag, "cannot find file '" + oc.local_path + "', file does not exists");
									}
										
								}
								img1.setImageBitmap(bmp);
								llAttachment.addView(img1);
							}
								
						} else {
							MyLog.e(tag, "Cannot find object_cache from fbid=" + fbid);
							GetPhotoFQL gp = new GetPhotoFQL(context, fbid, description, fp.post_id);

							this.gm.addNewQueue(gp, 2);
							
						}
					}
						
					llDetail.addView(attachmentV);
						
				} else {
					MyLog.w(tag, "Cannot find images for post_id=" + fp.post_id);
				}
					
				/*
				if (fp.status_text.equals(LikeManager.S_CHECKIN)) {
					JSONObject jAttachment = jo.getJSONObject("attachment");
					message = message + " @" + jAttachment.getString("name");
						
				}
				*/
				
				tvMessage.setText(message);
					
				llDetail.addView(tvMessage);
				
				if (fp.status_text.equals(LikeManager.S_LINK_POSTED)) {
					Button btnGo = new Button(this.context);					
					btnGo.setText("Go to link");
					llDetail.addView(btnGo);
					btnGo.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
					btnGo.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
					btnGo.setFocusable(false);
					btnGo.setFocusableInTouchMode(false);
					
					btnGo.setOnClickListener(this);
				}
			} catch (Exception e) {
				MyLog.e(tag, "getView() - " + e.toString(), e);
			}
		}
						
		return (item);
	}
	
	private ArrayList<String> getAttachmentFBID(JSONObject jo) {
		ArrayList<String> a = null;
		
		try {
			if (jo.has("attachment")) {
				JSONObject jAttachment = jo.getJSONObject("attachment");
				if (jAttachment.has("media")) {
					JSONArray jMediaArray = jAttachment.getJSONArray("media");
					int len = jMediaArray.length();
					int i;
					for (i = 0; i < len; i++) {
						JSONObject jMedia = (JSONObject) jMediaArray.get(i);
						String src;
						String fbid = null;
						String type = null;
						
						if (jMedia.has("type")) {
							type = jMedia.getString("type");
							//MyLog.d(tag, "type=" + type);
						}
						
						if (type.equals("photo")) {
							if (jMedia.has("src")) {
								
								src = jMedia.getString("src");
								//MyLog.d(tag, "src=" + src);
								
								if (type.equals("photo")) {
									if (jMedia.has("photo")) {
										JSONObject jPhoto = jMedia.getJSONObject("photo");
										fbid = jPhoto.getString("fbid");
									}
									
								} 
								
							}
							
						} else if (type.equals("link")) {
							fbid = jo.getString("post_id");
							MyLog.d(tag, "fbid=" + fbid);
							
						} else if (type.equals("video")) {
							fbid = jo.getString("post_id");
							MyLog.d(tag, "fbid=" + fbid);
						}
						
						if (fbid != null) {
							if (a == null) { a = new ArrayList<String>(); };
							a.add(fbid);
						}
					}
					
				} else {  // Not found media
					String post_id = jo.getString("post_id");
					String fbid = post_id.split("_")[1];
					if (a == null) { a = new ArrayList<String>(); };
					a.add(fbid);
					MyLog.d(tag, "fbid=" + fbid + " from non-media, post_id=" + post_id);
					//MyLog.d(tag, jo.toString());
					
				}
			}
		} catch (Exception e) {
			MyLog.e(tag, "getAttachmentSrcs() - " + e.toString(), e);
		}
		
		return(a);
	}

	public int updateRecord(FriendsPost fp) {
				
		if (fp == null) {
			MyLog.d(tag, "updateRecord failed coz fp == null");
			return(-1);
		}
		
		MyLog.d(tag, "updateRecord(" + fp.toString() + ")");
		
		int position = -1;
		
		position = TextUtils.insertArrayList(this.arrHistory, fp, "created_time", "desc", true);
		boolean requiredUpdateFiler = false;
		if (this.filterName.equals("") == false) {
			requiredUpdateFiler = true;	
		}
		
		if (this.isOnlyFriend == true) {
			requiredUpdateFiler = true;
		}
		
		if (requiredUpdateFiler == true) {
			this.updateFileredArrayList();
		}
		
		MyLog.d(tag, "position=" + position);
		
		return(position);
		
	}
	
	private void updateFileredArrayList() {
		this.arrFiltered.clear();
		int len = this.arrHistory.size();
		int i;
		for (i = 0; i < len; i++) {
			FriendsPost fp = (FriendsPost) this.arrHistory.get(i);
			FriendsList fl = this.service.getHashFriendsList().get(fp.actor_id);
			if (fl != null) {
				String name = fl.name;
				
				if (this.filterName.equals("") == false) {
					if ( (fp != null) && (name != null) && (name.toLowerCase().contains(this.filterName.toLowerCase()) == true) ) {
						if (this.isOnlyFriend == false) {
							this.arrFiltered.add(fp);
							//MyLog.d(tag, "add matched1: " + name);
						} else if (this.isOnlyFriend == true) {
							if (fl.is_friend.equals("Y") == true) {
								this.arrFiltered.add(fp);
								//MyLog.d(tag, "add matched2: " + name);
							}
						}
							
					}
					
				} else {
					if (this.isOnlyFriend == true) {
						if (fl.is_friend.equals("Y") == true) {
							this.arrFiltered.add(fp);

						}
					} else {
						this.arrFiltered.add(fp);

					}
				}
				
			}
			
			
		}		
	}
	
	public void setFilterByName(String name) {
		this.filterName = name;
		this.updateFileredArrayList();		
	}

	@Override
	public void onClick(View v) {
		/*
		Intent intent = new Intent(this.context, com.tnsw.facebookautoliker.LinkActivity.class);
		this.context.startActivity(intent);
		*/
		if (v.getId() == R.id.tvWhen) {
			TextView tvWhen = (TextView) v;
			
			MyLog.d(tag, "tvWhen is clicked");
			int position = (Integer) v.getTag(R.id.tag_position);
			MyLog.d(tag, "position=" + position);
			FriendsPost fp = (FriendsPost) this.getCurrentArrayList().get(position);
			//int mode = (Integer) v.getTag(R.id.tag_tvWhen_mode);
			int mode = fp.getWhenMode();
			MyLog.d(tag, "mode=" + mode);
			
			if (mode == 0) {
				String fbDateTime = TextUtils.getFBDateDiff(fp.created_time*1000, System.currentTimeMillis());
				tvWhen.setText(fbDateTime);
				mode = 1;
			} else {
				String stdDate = TextUtils.getMyStandardDateStr(fp.created_time*1000, TimeZone.getDefault().getID());
				tvWhen.setText(stdDate);
				
				mode = 0;
			}
						
			fp.setWhenMode(mode);
			
			v.setTag(R.id.tag_tvWhen_mode, mode);
			
		} else if (v.getId() == R.id.tvLikeUnlike) {
			int position = (Integer) v.getTag(R.id.tag_position);
			FriendsPost fp = (FriendsPost) this.getCurrentArrayList().get(position);
			
			/*
			if (fp.liked.equals("Y")) {
				fp.liked = "N";
			} else {
				fp.liked = "Y";
			}
			
			this.notifyDataSetChanged();
			*/
			AutoLikerService aService = AutoLikerService.getInstance();
			LikeManager lm = new LikeManager(context, aService.getSelfInfo());
			if (fp.liked.equals("Y")) {
				DoUnlikePost unlikePost = new DoUnlikePost(this.context, fp.post_id);
				unlikePost.setTag("caller", this);

				this.gm.addNewQueue(unlikePost, 2);
	
			} else {
				lm.doLike(fp.post_id, fp, null);
			}
			
		}
	}

	@Override
	public boolean onLongClick(View v) {
		
		if (v.getId() == R.id.tvWhen) {
			MyLog.d(tag, "tvWhen onLongClick");
			TextView tvWhen = (TextView) v;
			int position = (Integer) v.getTag(R.id.tag_position);
			MyLog.d(tag, "position=" + position);
			FriendsPost fp = (FriendsPost) this.getCurrentArrayList().get(position);
			//int mode = (Integer) v.getTag(R.id.tag_tvWhen_mode);
			int mode = fp.getWhenMode();
			int newMode;
			if (mode == 0) {
				newMode = 1;
			} else {
				newMode = 0;
			}
			
			int len = this.getCurrentArrayList().size();
			int i;
			for (i = 0; i < len; i++) {
				fp = (FriendsPost) this.getCurrentArrayList().get(i);
				fp.setWhenMode(newMode);
			}
			
			this.notifyDataSetChanged();
			
		}
		return true;
	}

	@Override
	public void onLayoutChange(View v, int left, int top, int right,
			int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
		int position = (Integer) v.getTag(R.id.tag_position);
		int height = bottom-top;
		MyLog.d(tag, "onLayoutChange() - position=" + position + ", height=" + (bottom-top));
		FriendsPost fp = (FriendsPost) v.getTag(R.id.tag_record);
		fp.setHeight(height);
		
		RelativeLayout layoutItemWait = (RelativeLayout) v.findViewById(R.id.layoutItemWait);
		layoutItemWait.getLayoutParams().height = height;
		layoutItemWait.requestLayout();
		
		this.notifyDataSetChanged();
	}
	
}
